﻿using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text;
using System.Xml;
using System.Collections.Generic;
using System.IO;

namespace GeoSketch2.Core
{
    /// <summary>
    /// The layer class
    /// </summary>
    [Serializable]
    public class Layer
    {
        #region XMLElementsName
#pragma warning disable 1591
        public const string XML_Name = "Name";
        public const string XML_LayerColor = "LayerColor";
        public const string XML_LineType = "LineType";
        public const string XML_Visible = "Visible";
        public const string XML_DisplayOrder = "DisplayOrder";
#pragma warning restore 1591
        #endregion

        #region Fields
        /// <summary>
        /// The name of the layer
        /// </summary>
        public string Name;

        /// <summary>
        /// The color of the Layer
        /// </summary>
        public Color LayerColor;

        /// <summary>
        /// The type of line of the layer
        /// </summary>
        public LineType LineType;

        /// <summary>
        /// The visibility of the layer
        /// </summary>
        public bool Visible;

        /// <summary>
        /// The display order of the layer 0 is the lowest level, below every other ones
        /// </summary>
        public int DisplayOrder;
        #endregion

        #region Constructor
        /// <summary>
        /// The layer for drawn object
        /// </summary>
        public Layer()
            :this("",Color.Black,new LineType(),true)
        {
        }

        /// <summary>
        /// The layer for drawn object
        /// </summary>
        /// <param name="Name">The name of the layer</param>
        /// <param name="LayerColor">The color of the Layer</param>
        /// <param name="LineType">The type of line of the layer</param>        
        /// <param name="Visible">The visibility of the layer</param>
        public Layer(string Name, Color LayerColor, LineType LineType, bool Visible)
            : this(Name, LayerColor, LineType, Visible, Vars.Setup.StandardObjects.Layer.NextAvailableDisplayOrder)
        {
            Vars.Setup.StandardObjects.Layer.NextAvailableDisplayOrder++;
        }

        /// <summary>
        /// The layer for drawn object
        /// </summary>
        /// <param name="Name">The name of the layer</param>
        /// <param name="LayerColor">The color of the Layer</param>
        /// <param name="LineType">The type of line of the layer</param>        
        /// <param name="Visible">The visibility of the layer</param>
        /// <param name="DisplayOrder">The display order of the layer</param>
        public Layer(string Name, Color LayerColor, LineType LineType, bool Visible,int DisplayOrder)
        {
            this.Name = Name;
            this.LayerColor = LayerColor;
            this.LineType = LineType;
            this.Visible = Visible;
            this.DisplayOrder = DisplayOrder;
        }

        /// <summary>
        /// The layer for drawn object
        /// </summary>
        /// <param name="Xr">The XmlReader to read from</param>
        /// <param name="LineTypeLibrary">The linetype library to get the linetype associated to the layer</param>
        public Layer(XmlReader Xr, List<LineType> LineTypeLibrary)
        {
            Xr.ReadToFollowing(XML_Name);
            this.Name = Xr.ReadString();

            Xr.ReadToFollowing(XML_LayerColor);
            this.LayerColor = Color.FromArgb(Convert.ToInt32(Xr.ReadString(), Vars.Setup.GeoSketch.NumberFormat)).GetNamedColor();

            Xr.ReadToFollowing(XML_LineType);
            int LineTypeId = Convert.ToInt32(Xr.ReadString());
            this.LineType = LineTypeLibrary.Find(delegate(LineType lt) { return lt.Id == LineTypeId; });

            Xr.ReadToFollowing(XML_Visible);
            this.Visible = Convert.ToBoolean(Xr.ReadString(), Vars.Setup.GeoSketch.NumberFormat);

            Xr.ReadToFollowing(XML_DisplayOrder);
            this.DisplayOrder = Convert.ToInt32(Xr.ReadString(), Vars.Setup.GeoSketch.NumberFormat);

            Xr.ReadEndElement();
        }
        #endregion

        #region Methods
        /// <summary>
        /// The ascending comparer for the display order of two layer
        /// </summary>
        /// <param name="Layer1">The first layer</param>
        /// <param name="Layer2">The second Layer</param>
        public static int CompareLayerDisplayOrderAsc(Layer Layer1, Layer Layer2)
        {
            if (Layer1.DisplayOrder == Layer2.DisplayOrder)
            {
                return 0;
            }
            else if (Layer1.DisplayOrder < Layer2.DisplayOrder)
            {
                return -1;
            }
            else
            {
                return 1;
            }
        }

        /// <summary>
        /// The descending comparer for the display order of two layer
        /// </summary>
        /// <param name="Layer1">The first layer</param>
        /// <param name="Layer2">The second Layer</param>
        public static int CompareLayerDisplayOrderDesc(Layer Layer1, Layer Layer2)
        {
            if (Layer1.DisplayOrder == Layer2.DisplayOrder)
            {
                return 0;
            }
            else if (Layer1.DisplayOrder < Layer2.DisplayOrder)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// The string display of the layer
        /// </summary>
        public override string ToString()
        {
            return Name;
        }

        /// <summary>
        /// Writes the object to a file
        /// </summary>
        /// <param name="Xw">The XmlReader to write to</param>
        public void ToFile(XmlWriter Xw)
        {
            Xw.WriteStartElement(this.GetType().FullName);

            #region Name
            Xw.WriteStartElement(XML_Name);
            Xw.WriteString(this.Name.ToString());
            Xw.WriteEndElement(); 
            #endregion

            #region LayerColor
            Xw.WriteStartElement(XML_LayerColor);
            Xw.WriteString(this.LayerColor.ToArgb().ToString(Vars.Setup.GeoSketch.NumberFormat));
            Xw.WriteEndElement(); 
            #endregion

            #region LineType
            Xw.WriteStartElement(XML_LineType);
            Xw.WriteString(this.LineType.Id.ToString(Vars.Setup.GeoSketch.NumberFormat));
            Xw.WriteEndElement(); 
            #endregion

            #region Visible
            Xw.WriteStartElement(XML_Visible);
            Xw.WriteString(this.Visible.ToString(Vars.Setup.GeoSketch.NumberFormat));
            Xw.WriteEndElement(); 
            #endregion

            #region Display Order
            Xw.WriteStartElement(XML_DisplayOrder);
            Xw.WriteString(this.DisplayOrder.ToString(Vars.Setup.GeoSketch.NumberFormat));
            Xw.WriteEndElement(); 
            #endregion

            Xw.WriteEndElement();
        }

        public void ToDXFR13(TextWriter Tw)
        {
            Tw.WriteLine("0");
            Tw.WriteLine("LAYER");

            Tw.WriteLine("2");
            Tw.WriteLine(this.Name);

            Tw.WriteLine("70");
            Tw.WriteLine("0");

            Tw.WriteLine("62");
            int AutoCadColor = AutoCadIndexedColor.GetNearestAutoCadColor(this.LayerColor).ACI;
            if (!this.Visible) { AutoCadColor *= -1; }
            Tw.WriteLine(AutoCadColor.ToString(Core.Vars.Setup.GeoSketch.NumberFormat));

            Tw.WriteLine("6");
            Tw.WriteLine(this.LineType.Id.ToString(Core.Vars.Setup.GeoSketch.NumberFormat));
        }
        #endregion

        #region Poperties
        /// <summary>
        /// Gets the menu item of the layer, for the drawing form
        /// </summary>
        public ToolStripMenuItem MenuItem
        {
            get
            {
                ToolStripMenuItem item = new ToolStripMenuItem(this.Name, MenuItemImageVisible);
                item.Tag = this;
                return item;
            }
        }

        /// <summary>
        /// Gets the colored bitmap of the layer with the color of the layer
        /// </summary>
        public Bitmap MenuItemImageVisible
        {
            get
            {
                return Tools.GetColoredSquare(LayerColor, Vars.Setup.StandardObjects.Layer.MenuItemsImageSize);
            }
        }

        /// <summary>
        /// Gets the colored bitmap of the layer when the layer is invisible
        /// </summary>
        public Bitmap MenuItemImageInvisible
        {
            get
            {
                return Tools.GetColoredSquare(Vars.Setup.StandardObjects.Layer.MenuItemsLayerInvisible, Vars.Setup.StandardObjects.Layer.MenuItemsImageSize);
            }
        } 
        #endregion
    }
}
